
/**
 * 比较两个变量是否相同
 * @param {Object} fobj
 * @param {Object} sobj
 * @return (Boolean)
 */
var compare = function(fobj, sobj) {
	var ftype = typeof(fobj);
	var stype = typeof(sobj);
	if (ftype == stype) {
		if (ftype == "object") {
			if (fobj.constructor == Array && sobj.constructor == Array) {
				return compareArray(fobj, sobj)
			} else if (fobj.constructor != Array && sobj.constructor != Array) {
				return compareObject(fobj, sobj);
			}
			return false;
		}
		return fobj == sobj;
	}
	return false;
}

/**
 * 比较两个对象是否相同
 * @param {Object} fobj
 * @param {Object} sobj
 * @return (Boolean)
 */
var compareObject = function(fobj, sobj) {
	for (var ele in fobj) {
		if (sobj[ele] == undefined) {
			return false;
		}
		if (!compare(fobj[ele], sobj[ele])) {
			return false;
		}
	}
	for (var ele in sobj) {
		if (fobj[ele] == undefined) {
			return false;
		}
		if (!compare(fobj[ele], sobj[ele])) {
			return false;
		}
	}
	return true;
}

/**
 * 对比两个数组是否相同
 * @param {Object} farr
 * @param {Object} sarr
 * @return (Boolean)
 */
var compareArray = function(farr, sarr) {
	if (farr.length != sarr.length) {
		return false;
	}
	for (var i = 0; i < farr.length; i++) {
		if (!compare(farr[i], sarr[i])) {
			return false;
		}
	}
	return true;
}

/**
 * 计算对象大小
 * @param {Object} obj
 * @author shenkong(shenkong@php.net)
 */
var count = function(obj) {
	var length = 0;
	if (typeof obj == 'object') {
		for (k in obj) {
			length++;
		}
	}
	return length;
}

/**
 * 检查数组中是否存在某个值
 * 在 haystack 中搜索 needle ，如果找到则返回 TRUE，否则返回 FALSE。
 * @param {Object} needle
 * @param {Object} haystack
 * @author shenkong(shenkong@php.net)
 */
var in_obj = function(needle, haystack) {
	for (key in haystack) {
		if (compare(needle, haystack[key])) {
			return true;
		}
	}
	return false;
}

/**
 * 检查给定的键名或索引是否存在于数组中
 * @param {Object} key
 * @param {Object} search
 * @author shenkong(shenkong@php.net)
 */
var obj_key_exists = function(key, search) {
	if (typeof key != 'number' && typeof key != 'string') {
		return false;
	}
	for (k in search) {
		if (k == key) {
			return true;
		}
	}
	return false;
}

/**
 * 返回 input 中所有的值并给其建立数字索引
 * @param {Object} input
 * @author shenkong(shenkong@php.net)
 */
var obj_values = function(input) {
	var o = [];
	for (key in input) {
		o.push(input[key]);
	}
	return o;
}

/**
 * 返回数组中所有的键名
 * 返回 input 数组中的数字或者字符串的键名。
 * 如果指定了可选参数 search_value ，则只返回该值的键名。否则 input 数组中的所有键名都会被返回。
 * @param {Object} input
 * @param {Object} search_value
 * @author shenkong(shenkong@php.net)
 */
var obj_keys = function(input, search_value) {
	if (typeof input != 'object') {
		return false;
	}
	var o = [];
	if (search_value == undefined) {
		for (key in input) {
			o.push(key);
		}
	} else {
		for (key in input) {
			if (compare(input[key], search_value)) {
				o.push(key);
			}
		}
	}
	return o;
}

/**
 * 创建一个数组，用一个数组的值作为其键名，另一个数组的值作为其值。
 * 如果两个数组的单元数不同或者数组为空时返回 FALSE。
 * 如果keys数组值有非字符串或数值的返回 FALSE。
 * @param {Object} keys
 * @param {Object} values
 * @author shenkong(shenkong@php.net)
 */
var obj_combine = function(keys, values) {
	if (keys.length != values.length) {
		return false;
	}
	if (keys.length == 0) {
		return false;
	}
	if (typeof keys != 'object' || typeof values != 'object') {
		return false;
	}
	var o = {};
	for (var i = 0; i < keys.length; i++) {
		if (typeof keys[i] != 'number' && typeof keys[i] != 'string') {
			return false;
		}
		o[keys[i]] = values[i];
	}
	return o;
}

/**
 * 在数组中搜索给定的值，如果成功则返回相应的键名
 * 在 haystack 中搜索 needle 参数并在找到的情况下返回键名，否则返回 FALSE。
 * 如果 needle 在 haystack 中出现不止一次，则返回第一个匹配的键。
 * 要返回所有匹配值的键，应该用 obj_keys() 加上可选参数 search_value 来代替。
 * @param {Object} needle
 * @param {Object} haystack
 * @author shenkong(shenkong@php.net)
 */
var obj_search = function(needle, haystack) {
	if (typeof haystack != 'object') {
		return false;
	}
	for (key in haystack) {
		if (compare(haystack[key], needle)) {
			return key;
		}
	}
	return false;
}

/**
 * 统计数组中所有的值出现的次数
 * 返回一个对象，该对象用 input 数组中的值作为键名，该值在 input 数组中出现的次数作为值。
 * @param {Object} input
 * @author shenkong(shenkong@php.net)
 */
var obj_count_values = function(input) {
	var o = {};
	for (key in input) {
		if (o[input[key]] == undefined) {
			o[input[key]] = 1;
		} else {
			o[input[key]]++;
		}
	}
	return o;
}

/**
 * 交换对象中的键和值
 * 返回一个反转后的 object，例如 trans 中的键名变成了值，而 trans 中的值成了键名。
 * 如果同一个值出现了多次，则最后一个键名将作为它的值，所有其它的都丢失了。
 * @param {Object} trans
 * @author shenkong(shenkong@php.net)
 */
var obj_flip = function(trans) {
	var o = {};
	for (key in trans) {
		o[trans[key]] = key;
	}
	return o;
}

/**
 * 返回对象的最后一个单元
 * @param {Object} obj
 * @author shenkong(shenkong@php.net)
 */
var end = function(obj) {
	for (key in obj) {
	}
	return obj[key];
}

/**
 * 将回调函数作用到给定数组的单元上
 * 返回一个对象，该对象包含了 arr1 中的所有单元经过 callback 作用过之后的单元。
 * callback 接受的参数数目应该和传递给 obj_map() 函数的数组数目一致。
 * @param {Object} callback
 * @author shenkong(shenkong@php.net)
 */
var obj_map = function(callback, arr1) {
	var o = [];

	if (callback == null) {
		callback = function() {
			var a = [];
			for (var i = 0; i < arguments.length; i++) {
				a.push(arguments[i]);
			}
			return a;
		}
	}

	for (var i = 1; i < arguments.length; i++) {
		arguments[i] = obj_values(arguments[i]);
	}
	var length = 0;
	for (var i = 1; i < arguments.length; i++) {
		if (arguments[i].length > length) {
			length = arguments[i].length;
		}
	}
	for (var i = 0; i < length; i++) {
		var cmd = [];

		for (var j = 1; j < arguments.length; j++) {
			cmd.push('arguments[' + j + '][' + i + ']');
		}
		cmd = 'o[' + i + '] = callback(' + cmd.join(',') + ')';
		eval(cmd);
	}
	return o;
}
